package com.zzyl.nursing.service.impl;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.time.temporal.WeekFields;
import java.util.*;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zzyl.common.exception.base.BaseException;
import com.zzyl.common.utils.DateUtils;
import com.zzyl.common.utils.StringUtils;
import com.zzyl.framework.web.service.TokenService;
import com.zzyl.nursing.domain.*;
import com.zzyl.nursing.dto.BindingFamilyMemberDto;
import com.zzyl.nursing.dto.UserLoginRequestDto;
import com.zzyl.nursing.dto.member.HealthIndexDataDto;
import com.zzyl.nursing.mapper.*;
import com.zzyl.nursing.service.IFamilyMemberElderService;
import com.zzyl.nursing.service.WechatService;
import com.zzyl.nursing.util.DateTimeZoneConverter;
import com.zzyl.nursing.vo.LoginVo;
import com.zzyl.nursing.vo.member.*;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.zzyl.nursing.service.IFamilyMemberService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import javax.servlet.http.HttpServletRequest;

/**
 * 老人家属Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-04-26
 */
@Service
public class FamilyMemberServiceImpl extends ServiceImpl<FamilyMemberMapper,FamilyMember> implements IFamilyMemberService
{
    @Autowired
    private FamilyMemberMapper familyMemberMapper;

    static List<String> DEFAULT_NICKNAME_PREFIX = ListUtil.of(
            "生活更美好",
            "大桔大利",
            "日富一日",
            "好柿开花",
            "柿柿如意",
            "一椰暴富",
            "大柚所为",
            "杨梅吐气",
            "天生荔枝"
    );

    /**
     * 查询老人家属
     * 
     * @param id 老人家属主键
     * @return 老人家属
     */
    @Override
    public FamilyMember selectFamilyMemberById(Long id)
    {
        return getById(id);
    }

    /**
     * 查询老人家属列表
     * 
     * @param familyMember 老人家属
     * @return 老人家属
     */
    @Override
    public List<FamilyMember> selectFamilyMemberList(FamilyMember familyMember)
    {
        return familyMemberMapper.selectFamilyMemberList(familyMember);
    }

    /**
     * 新增老人家属
     * 
     * @param familyMember 老人家属
     * @return 结果
     */
    @Override
    public int insertFamilyMember(FamilyMember familyMember)
    {
        return save(familyMember)?1:0;
    }

    /**
     * 修改老人家属
     * 
     * @param familyMember 老人家属
     * @return 结果
     */
    @Override
    public int updateFamilyMember(FamilyMember familyMember)
    {
        return updateById(familyMember)?1:0;
    }

    /**
     * 批量删除老人家属
     * 
     * @param ids 需要删除的老人家属主键
     * @return 结果
     */
    @Override
    public int deleteFamilyMemberByIds(Long[] ids)
    {
        return removeByIds(Arrays.asList(ids))?1:0;
    }

    /**
     * 删除老人家属信息
     * 
     * @param id 老人家属主键
     * @return 结果
     */
    @Override
    public int deleteFamilyMemberById(Long id)
    {
        return removeById(id)?1:0;
    }

    @Autowired
    private WechatService wechatService;

    @Autowired
    private TokenService tokenService;
    @Autowired
    private HttpServletRequest request;
    @Autowired
    private CheckInMapper checkInMapper;
    @Autowired
    private IFamilyMemberElderService familyMemberElderService;
    @Autowired
    private ElderMapper elderMapper;
    @Autowired
    private FamilyMemberElderMapper familyMemberElderMapper;
    @Autowired
    private BedMapper bedMapper;
    @Autowired
    private RoomMapper roomMapper;
    @Autowired
    private DeviceMapper deviceMapper;
    @Autowired
    private DeviceDataMapper deviceDataMapper;
    @Autowired
    private ContractMapper contractMapper;

    /**
     * 绑定家人
     *
     * @param dto
     */
    @Override
    public void bindingFamilyMember(BindingFamilyMemberDto dto) {
        //1、根据身份证号码查询老人数据
        CheckIn checkIn = checkInMapper.selectOne(Wrappers.<CheckIn>lambdaQuery()
                .eq(CheckIn::getIdCardNo, dto.getIdCard())
                .eq(CheckIn::getStatus, 0));
        //2、判断是否有这个老人
        if (ObjectUtil.isEmpty(checkIn)) {
            throw new BaseException("该老人没有入住！！！");
        }
        //判断输入的老人的姓名是否正确
        if (!dto.getName().equals(checkIn.getElderName())){
            throw new BaseException("请输入正确的老人姓名！！！");
        }
        //根据老人ID查询合同信息
        Contract contract = contractMapper.selectOne(Wrappers.<Contract>lambdaQuery()
                .eq(Contract::getElderId, checkIn.getElderId())
        );
        if (ObjectUtil.isEmpty(contract)){
            throw new BaseException("老人不存在！！！");
        }
        //3、获取家属id
        Claims claims = getClaims();
        //获取家属id
        Object id = claims.get("userId");
        Long userId = Long.valueOf(id.toString());
        //判断该用户是否重复绑定老人
        FamilyMemberElder memberElder = familyMemberElderMapper.selectOne(Wrappers.<FamilyMemberElder>lambdaQuery()
                .eq(FamilyMemberElder::getFamilyMemberId, userId));
        if (ObjectUtil.isNotEmpty(memberElder)){
            throw new BaseException("该用户已经绑定该老人了");
        }
        //创建家人和老人关系对象
        FamilyMemberElder familyMemberElder = new FamilyMemberElder();
        familyMemberElder.setElderId(checkIn.getElderId());
        familyMemberElder.setFamilyMemberId(userId);
        //保存绑定信息
        familyMemberElderService.save(familyMemberElder);
    }

    /**
     * 查询家人列表
     * @return 家人列表
     */
    @Override
    public List<FamilyMemberElderVo> getFamilyMemberList() {
        List<FamilyMemberElderVo> familyMemberElderVoList = new ArrayList<>();

        //获取token
        Claims claims = getClaims();
        //获取家属id
        Object id = claims.get("userId");
        Long userId = Long.valueOf(id.toString());
        //根据userid查询
        List<FamilyMemberElder> familyMemberElders = familyMemberElderService.list(Wrappers.<FamilyMemberElder>lambdaQuery()
                .eq(FamilyMemberElder::getFamilyMemberId, userId));
        //判空
        if (ObjectUtil.isEmpty(familyMemberElders)) {
            throw new BaseException("请先绑定老人！");
        }
        //遍历familyMemberElders集合
        familyMemberElders.forEach(familyMemberElder -> {
            Elder elder = elderMapper.selectElderById(familyMemberElder.getElderId());
            //创建老人和家属关系上传实体类
            FamilyMemberElderVo familyMemberElderVo = new FamilyMemberElderVo();
            familyMemberElderVo.setId(familyMemberElder.getId());
            familyMemberElderVo.setElderId(familyMemberElder.getElderId());
            familyMemberElderVo.setElderName(elder.getName());
            familyMemberElderVo.setFamilyMemberId(userId);
            familyMemberElderVoList.add(familyMemberElderVo);
        });
        return familyMemberElderVoList;
    }

    /**
     * 查看家人列表（分页查询）
     *
     * @return 家人列表
     */
    @Override
    public List<FamilyMemberElderListVo> getFamilyMemberListByPage() {
        List<FamilyMemberElderListVo> familyMemberElderListVoList = new ArrayList<>();
        //获取token
        Claims claims = getClaims();
        //获取家属id
        Object id = claims.get("userId");
        Long userId = Long.valueOf(id.toString());
        //根据userId查询老人家属关系表
        List<FamilyMemberElder> familyMemberElders = familyMemberElderMapper.selectList(Wrappers.<FamilyMemberElder>lambdaQuery()
                .eq(FamilyMemberElder::getFamilyMemberId, userId));
        if (ObjectUtil.isEmpty(familyMemberElders)) {
            throw new BaseException("请先绑定老人！！！");
        }
        //遍历集合familyMemberElders
        familyMemberElders.forEach(familyMemberElder -> {
            FamilyMemberElderListVo familyMemberElderListVo = new FamilyMemberElderListVo();
            familyMemberElderListVo.setMid(familyMemberElder.getId());
            familyMemberElderListVo.setMremark(familyMemberElder.getRemark());
            familyMemberElderListVo.setElderId(familyMemberElder.getElderId());
            //根据老人ID查询老人信息
            Elder elder = elderMapper.selectOne(Wrappers.<Elder>lambdaQuery()
                    .eq(Elder::getId, familyMemberElder.getElderId())
            );
            //将老人信息放入familyMemberElderListVo
            familyMemberElderListVo.setImage(elder.getImage());
            familyMemberElderListVo.setBedNumber(elder.getBedNumber());
            //根据床位ID获取床位信息
            Bed bed = bedMapper.selectOne(Wrappers.<Bed>lambdaQuery()
                    .eq(Bed::getId, elder.getId())
            );
            //根据房间ID查询房间信息
            Room room = roomMapper.selectOne(Wrappers.<Room>lambdaQuery()
                    .eq(Room::getId, bed.getRoomId()));
            //将房间信息放入familyMemberElderListVo
            familyMemberElderListVo.setTypeName(room.getTypeName());
            //根据老人ID查询设备信息
            Device device = deviceMapper.selectOne(Wrappers.<Device>lambdaQuery()
                    .eq(Device::getBindingLocation, elder.getId())
            );
            if (ObjectUtil.isEmpty(device)) {
                throw new BaseException("请先给"+elder.getName()+"绑定智能手表！！！");
            }
            //将设备数据放入familyMemberElderListVo
            familyMemberElderListVo.setIotId(device.getIotId());
            familyMemberElderListVo.setDeviceName(device.getDeviceName());
            familyMemberElderListVo.setProductKey(device.getProductKey());
            familyMemberElderListVoList.add(familyMemberElderListVo);
        });

        return familyMemberElderListVoList;
    }

    //获取token，并解析token方法
    private Claims getClaims() {
        //获取token
        String token = request.getHeader("authorization");
        //解析token
        Claims claims = tokenService.parseToken(token);
        return claims;
    }

    /**
     * 查询健康数据
     *
     * @param iotId 设备ID
     * @return 健康数据
     */
    @Override
    public List<HealthDataVo> queryServiceProperties(String iotId) {
        //根据设备ID查询设备数据
        List<DeviceData> dataList = deviceDataMapper.selectList(Wrappers.<DeviceData>lambdaQuery()
                .eq(DeviceData::getIotId, iotId)
                .orderByDesc(DeviceData::getAlarmTime));
        List<HealthDataVo> healthDataVoList = new ArrayList<>();
        //遍历设备数据
        dataList.forEach(data -> {
            HealthDataVo healthDataVo = new HealthDataVo();
            //处理时间格式
            LocalDateTime eventTimeStr = data.getAlarmTime();
            /*LocalDateTime localDateTime = DateUtil.parseLocalDateTime(eventTimeStr.toString(), "yyyy-MM-dd'T'HH:mm:ss");
            LocalDateTime alarmTime = DateTimeZoneConverter.utcToShanghai(localDateTime);*/
            healthDataVo.setEventTime(eventTimeStr);
            healthDataVo.setFunctionId(data.getFunctionId());
            healthDataVo.setValue(data.getDataValue());
            healthDataVoList.add(healthDataVo);
        });
        return healthDataVoList;
    }

    /**
     * 按天统计查询指标数据
     *
     * @param dto
     * @return
     */
    @Override
    public List<HealthIndexDataVo> queryDeviceDataListByDay(HealthIndexDataDto dto) {
        Instant instant = Instant.ofEpochMilli(dto.getStartTime());
        LocalDateTime start = LocalDateTime.ofInstant(instant, ZoneId.of("Asia/Shanghai"));
        Instant instant1 = Instant.ofEpochMilli(dto.getEndTime());
        LocalDateTime end = LocalDateTime.ofInstant(instant1, ZoneId.of("Asia/Shanghai"));

        // 过滤出符合时间范围内的数据
        List<DeviceData> deviceDataList = deviceDataMapper.selectList(Wrappers.<DeviceData>lambdaQuery()
                .between(DeviceData::getAlarmTime, start, end)
                .eq(DeviceData::getFunctionId, dto.getFunctionId()));

        List<HealthIndexDataVo> list = new ArrayList<>();

        if (CollUtil.isEmpty(deviceDataList)){
            throw new BaseException("没有符合条件的数据");
        }

        // 用两个Map分别存储每个小时的总和与数量
        Map<Integer, Double> hourSumMap = new HashMap<>();
        Map<Integer, Integer> hourCountMap = new HashMap<>();
        for (DeviceData data : deviceDataList) {
            int hour = data.getAlarmTime().getHour();
            double value = Double.parseDouble(data.getDataValue());
            //hourSumMap每个小时对应的数据总和
            hourSumMap.put(hour, hourSumMap.getOrDefault(hour, 0.0) + value);
            //hourCountMap每个小时对应的个数
            hourCountMap.put(hour, hourCountMap.getOrDefault(hour, 0) + 1);
        }

        // 构建结果时，每个小时创建一个新的vo对象
        for (int hour = 0; hour < 24; hour++) {
            // 关键修复：在循环内部创建新对象
            HealthIndexDataVo vo = new HealthIndexDataVo();
            //将整数小时值转换为固定格式的两位数字符串，并在后面追加:00表示整点时间
            vo.setDateTime(String.format("%02d:00", hour));
            //拿到每个时间点的总和
            double sum = hourSumMap.getOrDefault(hour, 0.0);
            //
            int count = hourCountMap.getOrDefault(hour, 0);

            vo.setDataValue(count > 0 ? sum / count : 0.0);
            list.add(vo);
        }

        return list;
    }

    /**
     * 按周统计查询指标数据
     *
     * @param dto
     * @return
     */
    @Override
    public List<HealthIndexDataVo> queryDeviceDataListByWeek(HealthIndexDataDto dto) {
        // 1. 解析前端传入的毫秒值
        Instant instant = Instant.ofEpochMilli(dto.getEndTime());
        LocalDate currentDate = LocalDate.ofInstant(instant, ZoneId.of("Asia/Shanghai"));

        // 2. 计算前几天的日期
        LocalDate startDate = currentDate.minusDays(7);

        // 结束日期设为当前日期
        LocalDate endDate = LocalDate.now();

        // 3. 从数据库查询近7天的数据（包含开始和结束日期）
        List<DeviceData> deviceDataList = deviceDataMapper.selectList(Wrappers.<DeviceData>lambdaQuery()
                .between(DeviceData::getAlarmTime, startDate, endDate)
                .eq(DeviceData::getFunctionId, dto.getFunctionId()));

        if (CollUtil.isEmpty(deviceDataList)) {
            throw new BaseException("没有符合条件的数据");
        }

        List<HealthIndexDataVo> resultList = new ArrayList<>();

        // 4. 按每月的日期（1-31）分组统计
        Map<Integer, Double> daySumMap = new HashMap<>();
        Map<Integer, Integer> dayCountMap = new HashMap<>();
        for (DeviceData data : deviceDataList) {
            // 关键修复：使用每月的日期（1-31）作为分组依据，而非星期
            int dayOfMonth = data.getAlarmTime().getDayOfMonth();
            double value = Double.parseDouble(data.getDataValue());

            daySumMap.put(dayOfMonth, daySumMap.getOrDefault(dayOfMonth, 0.0) + value);
            dayCountMap.put(dayOfMonth, dayCountMap.getOrDefault(dayOfMonth, 0) + 1);
        }

        // 5. 循环近7天的日期（自动处理跨月情况）
        for (int i = 0; i <= 7; i++) {
            // 从7天前开始，依次取每天的日期
            LocalDate loopDate = startDate.plusDays(i);
            int dayOfMonth = loopDate.getDayOfMonth();

            HealthIndexDataVo vo = new HealthIndexDataVo();
            // 格式化日期
            vo.setDateTime(String.format("%02d.%02d", loopDate.getMonthValue(), dayOfMonth));

            double sum = daySumMap.getOrDefault(dayOfMonth, 0.0);
            int count = dayCountMap.getOrDefault(dayOfMonth, 0);

            int value = count > 0 ? (int) Math.round(sum / count) : 0;
            vo.setDataValue(Double.valueOf(value));
            resultList.add(vo);
        }

        return resultList;
    }

    /**
     * 小程序端登录
     * @param dto
     * @return
     */
    @Override
    public LoginVo login(UserLoginRequestDto dto) {

        //获取openid  微信接口获取
        String openid = wechatService.getOpenid(dto.getCode());

        //根据openid查询用户信息
        FamilyMember familyMember = getOne(Wrappers.<FamilyMember>lambdaQuery().eq(FamilyMember::getOpenId, openid));

        //如果用户为空，构建用户，赋值一个openid
        if(ObjectUtil.isEmpty(familyMember)){
            familyMember = FamilyMember
                    .builder()
                    .openId(openid)
                    .build();
        }

        //获取用户的手机号  微信接口获取
        String phone = wechatService.getPhone(dto.getPhoneCode());

        //保存或更新用户
        insertOrUpdateFamilyMember(familyMember,phone);

        //生成token返回
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", familyMember.getId());
        claims.put("userName", familyMember.getName());

        String token = tokenService.createToken(claims);
        LoginVo loginVo = new LoginVo();
        loginVo.setNickName(familyMember.getName());
        loginVo.setToken(token);

        return loginVo;
    }

    /**
     * 保存或更新用户
     * @param familyMember
     * @param phone
     */
    private void insertOrUpdateFamilyMember(FamilyMember familyMember, String phone) {

        //判断手机号与数据库的手机号是否一致
        if(ObjectUtil.notEqual(familyMember.getPhone(),phone)){
            familyMember.setPhone(phone);
        }
        //判断是否存在id，如果存在id，则更新，不存在则保存
        if(ObjectUtil.isNotEmpty(familyMember.getId())){
            updateById(familyMember);
            return;
        }
        //获取用户的昵称
        int index = (int)(Math.random() * DEFAULT_NICKNAME_PREFIX.size());
        String nickName = DEFAULT_NICKNAME_PREFIX.get(index) + StringUtils.substring(phone,7,11);
        familyMember.setName(nickName);
        //保存
        save(familyMember);

    }
}
